namespace classifier_test
{

enum attribute_type { cont_attr, discr_attr };

string attribute_type_to_str(const attribute_type& Type);
attribute_type str_to_attribute_type(const string& S);

void serialize(serializer& Serializer, attribute_type& Val);

typedef float cont_value;
typedef short discr_value;

union attribute_value
{
	cont_value cont;
	discr_value discr;
};

typedef array<attribute_value> record;

struct cont_domain
{
	cont_value lower_bound, upper_bound;

	cont_domain(double SetLBound = 0, double SetUBound = 0)
		: lower_bound((cont_value)SetLBound), upper_bound((cont_value)SetUBound)
	{
	}
	bool valid(double Val) const
	{
		return Val >= lower_bound && Val <= upper_bound;
	}
	void serialize(serializer& Serializer);
};

struct discr_domain
{
	discr_value count;

	explicit discr_domain(int SetCount = 0)
		: count(SetCount)
	{
	}
	bool valid(int Val) const
	{
		return Val >= 0 && Val < count;
	}
	void serialize(serializer& Serializer);
};

struct attribute_domain
{
	attribute_type type;
	cont_domain cont;
	discr_domain discr;

	attribute_domain()
		: type(cont_attr)
	{
	}
	attribute_domain(const cont_domain& Val)
		: type(cont_attr), cont(Val)
	{
	}
	attribute_domain(const discr_domain& Val)
		: type(discr_attr), discr(Val)
	{
	}
	bool valid(attribute_value Val) const
	{
		if (type == cont_attr) return cont.valid(Val.cont);
		if (type == discr_attr) return discr.valid(Val.discr);
		return false;
	}
	void serialize(serializer& Serializer);
};

struct record_domain : public array<attribute_domain>
{
	record_domain(int SetSize = 0, const attribute_domain& SetValue = attribute_domain())
		: array<attribute_domain>(SetSize, SetValue)
	{
	}
	bool valid(const record& Val) const;
	void serialize(serializer& Serializer);
};

}
